﻿#region

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel;
using System.Threading;
using System.Windows.Browser;
using Radovici.Ctrls.Facebook;
using Radovici.SharedLibrary;
using Wintellect.PowerCollections;
using YouTubePlaylist.Adapters;
using YouTubePlaylist.MusicVideoService;

#endregion

namespace YouTubePlaylist.Models
{
    public class DataLayer : Progressable
    {
        //public const string EndPoint = "http://localhost:8080/";
        public const string EndPoint = "http://wusic.net:8080/";
        //public const string EndPoint = "http://v2.wusic.net/";

        #region Static functionality

        #region Static fields

        private static readonly string _appName = HtmlPage.Document.DocumentUri.Host;
        private static readonly DataLayer _sharedSingleton = new DataLayer();

        #endregion

        public static DataLayer Singleton
        {
            get { return _sharedSingleton; }
        }

        private static IDictionary<string, string> QueryString
        {
            get { return HtmlPage.Document.QueryString; }
        }

        public static Dictionary<string, string> DefaultPreferences
        {
            get
            {
                var preferences = new Dictionary<string, string>();
                BrowserInformation info = HtmlPage.BrowserInformation;
                preferences["BrowserInformation"] = string.Format("{0},{1},{2},{3},{4}", 
                    info.UserAgent, info.Name, info.BrowserVersion, info.CookiesEnabled, info.Platform);
                preferences["AppName"] = _appName;
                return preferences;
            }
        }

        private static User DefaultUser
        {
            get
            {
                var u = new User
                            {
                                //ExternalKey = FacebookApi.FacebookUser.DefaultUserId
                                ExternalKey = Cookies.Load("ExternalKey") ?? "demo"
                            }; //TODO: Serialize objects to cookies.
                return u;
            }
        }

        #endregion

        #region Private fields

        private readonly MusicVideoServiceClient _client = new MusicVideoServiceClient(
                new BasicHttpBinding { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue },
                new EndpointAddress(EndPoint + "MusicVideoService.svc"));
        private static readonly Dictionary<int, VideoTrack> _allTracks = new Dictionary<int, VideoTrack>();
        private readonly Dictionary<int, VideoPlaylist> _allPlaylists = new Dictionary<int, VideoPlaylist>();
        private readonly OrderedSet<LogMessage> _logMessages = new OrderedSet<LogMessage>(new Comparison<LogMessage>(CompareLogMessages));
        private readonly Timer _refreshTimer;
        private VideoPlaylist _linkedPlaylist;
        private User _user;

        #region Playlists

        private readonly ObservableCollection<VideoPlaylist> _mostRecentlyCreatedPlaylists =
            new ObservableCollection<VideoPlaylist>();

        private readonly ObservableCollection<VideoPlaylist> _mostRecentlyUpdatedPlaylists =
            new ObservableCollection<VideoPlaylist>();

        private readonly ObservableCollection<VideoPlaylist> _myPlaylists =
            new ObservableCollection<VideoPlaylist>();

        private readonly ObservableCollection<VideoPlaylist> _playingPlaylists =
            new ObservableCollection<VideoPlaylist>();

        #endregion

        private static int CompareLogMessages(LogMessage l1, LogMessage l2)
        {
            return l2.Id.CompareTo(l1.Id); //NOTE: Orderby desc (!?)
        }

        #endregion

        private DataLayer()
        {
            InitializeUser();
            MonitorPlaylists();
            RegisterServiceCallbacks();
            _refreshTimer = new Timer(OnRefreshTimerCallBack, null, int.MaxValue, int.MaxValue);
            if (QueryString != null && QueryString.Count != 0 && QueryString.ContainsKey("playlist"))
            {
                _client.GetPlaylistAsync(User, Convert.ToInt32(QueryString["playlist"]),
                                         new ProgressableState(this, _playingPlaylists, "Getting Linked Playlist"));
            }
            //FacebookApi.PropertyChanged += OnFacebookApiChanged;
        }

        //public string FacebookApiKey
        //{
        //    get { return "5716ce903d9a344ce4f5a1c6491ba3ae"; }
        //}

        //public FacebookApi FacebookApi
        //{
        //    get { return FacebookApi.GetFacebookApi(FacebookApiKey); }
        //}

        //private void OnFacebookApiChanged(object sender, PropertyChangedEventArgs e)
        //{
        //    _user.ExternalKey = FacebookApi.User.UserId;
        //    if (e.PropertyName == "User.Friends")
        //    {
        //        _user.Preferences["FacebookFriends"] = FacebookApi.User.Friends.Join(item => item.UserId);
        //        UpdatePreferences();
        //    }
        //    Notify("FacebookApi");
        //    Notify("LogMessages");
        //    if (e.PropertyName == "User")
        //    {
        //        _client.GetLogMessagesAsync(_user, 20, new ProgressableState(this, null, "Getting Wessages"));
        //    }
        //    //foreach(FacebookApi.FacebookUser fbUser in FacebookApi.User.Friends)
        //    //{
        //    //    _client.GetLogMessagesAsync(new User(){ ExternalKey = fbUser.UserId}, 20, new ProgressableState(this, null, "Getting Wessages"));
        //    //}
        //}
        public IEnumerable<LogMessage> LogMessages
        {
            get { return _logMessages.Take(20); }
        }

        public ObservableCollection<VideoPlaylist> PlayingPlaylists
        {
            get { return _playingPlaylists; }
        }

        public ObservableCollection<VideoPlaylist> MyPlaylists
        {
            get { return _myPlaylists; }
        }

        public ObservableCollection<VideoPlaylist> MostRecentlyCreatedPlaylists
        {
            get { return _mostRecentlyCreatedPlaylists; }
        }

        public ObservableCollection<VideoPlaylist> MostRecentlyUpdatedPlaylists
        {
            get { return _mostRecentlyUpdatedPlaylists; }
        }

        public VideoPlaylist LinkedPlaylist
        {
            get
            {
                return _linkedPlaylist;
                //if (QueryString != null && QueryString.ContainsKey("playlist"))
                //{
                //    return Convert.ToInt32(QueryString["playlist"]);
                //}
                //else if (_user.Preferences.ContainsKey("CurrentPlaylist"))
                //{
                //    return Convert.ToInt32(_user.Preferences["CurrentPlaylist"]);
                //}
                //return 0;
            }
        }

        public VideoTrack LinkedTrack
        {
            get
            {
                if (_linkedPlaylist != null)
                {
                    if (QueryString != null && QueryString.ContainsKey("track"))
                    {
                        return _linkedPlaylist.Tracks.SingleOrDefault(t => t.Id == Convert.ToInt32(QueryString["track"]));
                    }
                    if (_user.Preferences.ContainsKey("CurrentTrack"))
                    {
                        return
                            _linkedPlaylist.Tracks.SingleOrDefault(
                                t => t.Id == Convert.ToInt32(_user.Preferences["CurrentTrack"]));
                    }
                }
                return null;
            }
        }

        public VideoPlaylist GetPlaylist(int playlistId, Action callback)
        {
            if (_allPlaylists.ContainsKey(playlistId))
            {
                return _allPlaylists[playlistId];
            }
            _client.GetPlaylistAsync(_user, playlistId, new ProgressableState(this, null, null, callback));
            return null;
        }

        public VideoTrack GetTrack(int trackId, Action callback)
        {
            if (_allTracks.ContainsKey(trackId))
            {
                return _allTracks[trackId];
            }
            _client.GetTrackAsync(_user, trackId, new ProgressableState(this, null, null, callback));
            return null;
        }

        public bool CanUserAddNew(ObservableCollection<VideoPlaylist> playlists)
        {
            return (playlists == _myPlaylists);
        }

        public bool CanUserAdd(ObservableCollection<VideoPlaylist> playlists)
        {
            return (playlists == _myPlaylists || playlists == _playingPlaylists);
        }

        public bool CanUserDelete(ObservableCollection<VideoPlaylist> playlists)
        {
            return (playlists == _myPlaylists || playlists == _playingPlaylists);
        }

        public bool CanUserEdit(ObservableCollection<VideoPlaylist> playlists)
        {
            return CanUserAddNew(playlists);
        }

        public void DeletePlaylist(VideoPlaylist playlist, ObservableCollection<VideoPlaylist> playlists)
        {
            if (playlists == _myPlaylists)
            {
                if (_myPlaylists.Contains(playlist))
                {
                    _myPlaylists.Remove(playlist);
                    _client.DeletePlaylistAsync(_user, playlist.Id);
                }
            }
            else
            {
                playlists.Remove(playlist);
            }
        }

        public void DeleteTrack(VideoPlaylist playlist, VideoTrack track)
        {
            if (_myPlaylists.Contains(playlist))
            {
                playlist.Tracks.Remove(track);
                _client.DeleteTrackFromPlaylistAsync(_user, playlist.Id, track.Id);
            }
        }

        #region SaveTrackUrl

        public void SaveTrackUrl(VideoTrack track)
        {
            _client.SaveTrackUrlAsync(User, track.Id, track.SelectedUrl.Id, null); //new ProgressableState(this, null, "Setting Track's Default Video"));
        }

        private void OnSaveTrackUrlCompleted(object sender, SaveTrackUrlCompletedEventArgs e)
        {
            VideoTrack t = e.Result;
            if (t != null)
            {
                UpdateTrack(t);
            }
            _client.GetLogMessagesAsync(User, 5);
        }

        #endregion

        #region RefreshTrack

        public void RefreshTrack(VideoTrack track)
        {
            _client.RefreshTrackAsync(User, track.Id, new ProgressableState(this, null, "Refresh Track's Videos"));
        }

        private void OnRefreshTrackCompleted(object sender, RefreshTrackCompletedEventArgs e)
        {
            VideoTrack t = e.Result;
            if (t != null)
            {
                UpdateTrack(t);
            }
            _client.GetLogMessagesAsync(User, 5);
        }

        #endregion

        #region GetUser

        public void GetUser()
        {
            _client.GetUserAsync(User, _user.ExternalKey, new ProgressableState(this, null, "Getting User"));
        }

        private void OnGetUserCompleted(object sender, GetUserCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                var state = e.UserState as ProgressableState;
                if (state != null)
                {
                    _logMessages.Clear();
                    using (state)
                    {
                        _user = e.Result;
                        InitializePreferences();
                        _user.PropertyChanged += OnUserChanged;
                        Notify("User");
                        //Initialize user's (i.e., my) playlists
                        RefreshPlaylists();

                        if (_user.Preferences.ContainsKey("Playing"))
                        {
                            string nowPlaying = _user.Preferences["Playing"];
                            if (!string.IsNullOrEmpty(nowPlaying))
                            {
                                QueuePlaylists(nowPlaying.Split(',', s => int.Parse(s)));
                            }
                        }

                        //Cookies.Save("ExternalKey", _user.ExternalKey);
                        if ((QueryString == null || QueryString.Count == 0) &&
                            _user.Preferences.ContainsKey("CurrentPlaylist"))
                        {
                            _client.GetPlaylistAsync(User, Convert.ToInt32(_user.Preferences["CurrentPlaylist"]),
                                                     new ProgressableState(this, _playingPlaylists, "Getting Last Track"));
                        }
                        _refreshTimer.Change(0, 600000);
                    }
                    _client.GetLogMessagesAsync(User, 20, new ProgressableState(this, null, "Getting Wessages"));
                }
            }
        }

        #endregion

        #region Update calls

        public void QueuePlaylist(VideoPlaylist p)
        {
            UpdatePlaylists(_playingPlaylists, p);
        }

        public void QueuePlaylists(IEnumerable<int> playlistIds)
        {
            _client.GetPlaylistsFromIdsAsync(_user, playlistIds.ToObservableCollection(),
                                             new ProgressableState(this, _playingPlaylists,
                                                                   string.Format("Getting Select Playlists")));
        }

        internal void AddPlaylist(VideoPlaylist playlist) //NOTE: This shouldn't be exposed publicly.
        {
            AddPlaylist(playlist, _myPlaylists);
        }

        public void AddPlaylist(VideoPlaylist playlist, ObservableCollection<VideoPlaylist> playlists)
        {
            if (playlists == MyPlaylists)
            {
                _client.AddPlaylistAsync(_user, playlist, new ProgressableState(this, _myPlaylists, "Adding Playlist"));
            }
            else //if (playlists == PlayingPlaylists)
            {
                playlists.Add(playlist);
            }
        }

        public void RefreshPlaylists()
        {
            _myPlaylists.Clear();
                //TODO: Cache old _myPlaylists and compare to ensure atomic operation (or appearence of an atomic op).
            _client.GetPlaylistsAsync(_user, new ProgressableState(this, _myPlaylists, "Getting Playlists"));
        }

        public void AddPlaylists(ObservableCollection<VideoPlaylist> playlists)
        {
            _client.AddPlaylistsAsync(_user, playlists, new ProgressableState(this, _myPlaylists, "Adding Playlists"));
        }

        public void AddTrack(VideoPlaylist playlist, VideoTrack track)
        {
            _client.AddTrackAsync(_user, playlist.Id, track, new ProgressableState(this, _myPlaylists, "Adding Track"));
        }

        public void AddTracks(VideoPlaylist playlist, IEnumerable<VideoTrack> tracks)
        {
            var tmpTracks = new ObservableCollection<VideoTrack>();
            foreach (VideoTrack track in tracks)
            {
                tmpTracks.Add(track);
            }
            _client.AddTracksAsync(_user, playlist.Id, tmpTracks,
                                   new ProgressableState(this, _myPlaylists, "Adding Tracks"));
        }

        public void CopyPlaylist(VideoPlaylist playlist)
        {
            _client.CopyPlaylistAsync(_user, playlist.Id, new ProgressableState(this, _myPlaylists, "Copying Playlist"));
        }

        #endregion

        #region Update callbacks

        private void OnGetTrackCompleted(object sender, GetTrackCompletedEventArgs e)
        {
            using (e.UserState as ProgressableState)
            {
                if (e.Error == null && e.Result != null)
                {
                    MaintainTrack(e.Result);
                }
            }
        }

        private void OnGetPlaylistCompleted(object sender, GetPlaylistCompletedEventArgs e)
        {
            using (var ps = e.UserState as ProgressableState)
            {
                if (e.Error == null && e.Result != null)
                {
                    //HACK: Should properly separate functionality
                    if (!string.IsNullOrEmpty(ps.Status))
                    {
                        OnGetPlaylistsCompleted(ps, e.Error, new ObservableCollection<VideoPlaylist> {e.Result});
                        _linkedPlaylist = _allPlaylists[e.Result.Id];
                        Notify("LinkedTrack");
                    }
                    else
                    {
                        UpdatePlaylist(e.Result);
                    }
                }
            }
        }

        private void OnAddTrackCompleted(object sender, AddTrackCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error,
                                    new ObservableCollection<VideoPlaylist> {e.Result});
        }

        private void OnAddTracksCompleted(object sender, AddTracksCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error,
                                    new ObservableCollection<VideoPlaylist> {e.Result});
        }

        private void OnCopyPlaylistCompleted(object sender, CopyPlaylistCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error,
                                    new ObservableCollection<VideoPlaylist> {e.Result});
        }

        private void OnAddPlaylistCompleted(object sender, AddPlaylistCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error,
                                    new ObservableCollection<VideoPlaylist> {e.Result});
        }

        private void OnAddPlaylistsCompleted(object sender, AddPlaylistsCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error, e.Result);
        }

        private void OnGetPlaylistsFromIdsCompleted(object sender, GetPlaylistsFromIdsCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error, e.Result);
        }

        private void OnGetPlaylistsCompleted(object sender, GetPlaylistsCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error, e.Result);
        }

        private void OnGetMostRecentlyCreatedPlaylists(object sender,
                                                       GetMostRecentlyCreatedPlaylistsCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error, e.Result);
        }

        private void OnGetMostRecentlyUpdatedPlaylists(object sender,
                                                       GetMostRecentlyUpdatedPlaylistsCompletedEventArgs e)
        {
            OnGetPlaylistsCompleted(e.UserState as ProgressableState, e.Error, e.Result);
        }

        private void OnGetPlaylistsCompleted(ProgressableState state, Exception error,
                                             ObservableCollection<VideoPlaylist> playlists)
        {
            using (state)
            {
                if (error == null && playlists != null && playlists.Count > 0)
                {
                    Context.Send(delegate
                                     {
                                         var curPlaylists = state.State as ObservableCollection<VideoPlaylist>;
                                         if (curPlaylists == _myPlaylists)
                                         {
                                             UpdatePlaylists(curPlaylists, playlists);
                                             Notify("MyPlaylists");
                                         }
                                         else if (curPlaylists == _mostRecentlyCreatedPlaylists)
                                         {
                                             UpdatePlaylists(curPlaylists, playlists);
                                             if (_mostRecentlyCreatedPlaylists.Count > 5)
                                             {
                                                 _mostRecentlyCreatedPlaylists.Clear();
                                                 UpdatePlaylists(curPlaylists, playlists);
                                             }
                                             Notify("MostRecentlyCreatedPlaylists");
                                         }
                                         else if (curPlaylists == _mostRecentlyUpdatedPlaylists)
                                         {
                                             UpdatePlaylists(curPlaylists, playlists);
                                             if (_mostRecentlyUpdatedPlaylists.Count > 5)
                                             {
                                                 _mostRecentlyUpdatedPlaylists.Clear();
                                                 UpdatePlaylists(curPlaylists, playlists);
                                             }
                                             Notify("MostRecentlyUpdatedPlaylists");
                                         }
                                         else if (curPlaylists == _playingPlaylists)
                                         {
                                             UpdatePlaylists(curPlaylists, playlists);
                                             Notify("PlayingPlaylists");
                                         }
                                         _client.GetLogMessagesAsync(User, 5);
                                     }, null);
                }
            }
        }

        #endregion

        #region Update mechanisms

        private void UpdatePlaylists(ObservableCollection<VideoPlaylist> tarPlaylists,
                                     IEnumerable<VideoPlaylist> playlists)
        {
            foreach (VideoPlaylist playlist in playlists)
            {
                UpdatePlaylists(tarPlaylists, playlist);
            }
        }

        private void UpdatePlaylists(ObservableCollection<VideoPlaylist> tarPlaylists, VideoPlaylist playlist)
        {
            playlist = UpdatePlaylist(playlist);
            VideoPlaylist exPlaylist = tarPlaylists.SingleOrDefault(p => p.Id == playlist.Id);
            if (exPlaylist == null)
            {
                Context.Send(delegate { tarPlaylists.Add(playlist); }, null);
            }
        }

        private VideoPlaylist UpdatePlaylist(VideoPlaylist playlist)
        {
            Context.Send(delegate
                             {
                                 if (_allPlaylists.ContainsKey(playlist.Id))
                                 {
                                     VideoPlaylist oldPlaylist = _allPlaylists[playlist.Id];
                                     oldPlaylist.Copy(playlist);
                                     playlist = oldPlaylist;
                                 }
                                 else
                                 {
                                     _allPlaylists[playlist.Id] = playlist;
                                 }
                             }, null);
            return playlist;
        }

        private void UpdateTrack(VideoTrack track)
        {
            //NOTE: Better algorithm; this is too manual. What if we add another playlist?
            UpdateTrack(_myPlaylists, track);
            UpdateTrack(_playingPlaylists, track);
            UpdateTrack(_mostRecentlyCreatedPlaylists, track);
            UpdateTrack(_mostRecentlyCreatedPlaylists, track);
        }

        private void UpdateTrack(IEnumerable<VideoPlaylist> playlists, VideoTrack track)
        {
            foreach (VideoPlaylist playlist in playlists)
            {
                playlist.UpdateTrack(track);
            }
        }

        public static void MaintainTrack(VideoTrack track)
        {
            if (!_allTracks.ContainsKey(track.Id))
            {
                _allTracks[track.Id] = track;
            }
        }

        #endregion

        #region Private methods

        private void OnRefreshTimerCallBack(object state)
        {
            _client.GetMostRecentlyCreatedPlaylistsAsync(User, 5,
                                                         new ProgressableState(this, _mostRecentlyCreatedPlaylists, "Getting Most Recent Playlists"));
            _client.GetMostRecentlyUpdatedPlaylistsAsync(User, 5,
                                                         new ProgressableState(this, _mostRecentlyUpdatedPlaylists, "Getting Most Active Playlists"));
            _client.GetLogMessagesAsync(User, 20, new ProgressableState(this, null, "Getting Wessages"));
        }

        private void MonitorPlaylists()
        {
            _playingPlaylists.CollectionChanged += OnPlayingPlaylistsChanged;
        }

        private void RegisterServiceCallbacks()
        {
            _client.AddPlaylistCompleted += OnAddPlaylistCompleted;
            _client.AddPlaylistsCompleted += OnAddPlaylistsCompleted;
            _client.AddTrackCompleted += OnAddTrackCompleted;
            _client.AddTracksCompleted += OnAddTracksCompleted;
            _client.CopyPlaylistCompleted += OnCopyPlaylistCompleted;
            _client.GetPlaylistCompleted += OnGetPlaylistCompleted;
            _client.GetPlaylistsCompleted += OnGetPlaylistsCompleted;
            _client.GetPlaylistsFromIdsCompleted += OnGetPlaylistsFromIdsCompleted;
            _client.GetTrackCompleted += OnGetTrackCompleted;
            _client.GetUserCompleted += OnGetUserCompleted;
            _client.GetMostRecentlyCreatedPlaylistsCompleted += OnGetMostRecentlyCreatedPlaylists;
            _client.GetMostRecentlyUpdatedPlaylistsCompleted += OnGetMostRecentlyUpdatedPlaylists;
            _client.RefreshTrackCompleted += OnRefreshTrackCompleted;
            _client.SaveTrackUrlCompleted += OnSaveTrackUrlCompleted;
            _client.GetLogMessagesCompleted += OnGetLogMessagesCompleted;
            //_client.PublishLogMessageCompleted += OnPublishLogMessageCompleted;
        }

        private void OnGetLogMessagesCompleted(object sender, GetLogMessagesCompletedEventArgs e)
        {
            if (e.Error == null && e.Result != null)
            {
                using (e.UserState as ProgressableState)
                {
                    Context.Send(
                        delegate
                            {
                                _logMessages.AddMany(e.Result);
                                //foreach (LogMessage msg in e.Result)
                                //{
                                //    if (!_logMessages.Contains(msg))
                                //    {
                                //        _logMessages.Add(msg); //TODO: Sorted list (would be correct).
                                //    }
                                //}                            
                            }
                        , null);
                    Notify("LogMessages");
                }
            }
        }

        //#region FacebookIntegration
        //public void Publish(LogMessage msg)
        //{
        //    _client.PublishLogMessageAsync(User, msg.Id, new ProgressableState(this, msg, string.Format("Publishing {0}", msg.Display)));
        //}

        //private void OnPublishLogMessageCompleted(object sender, PublishLogMessageCompletedEventArgs e)
        //{
        //    if (e.Error == null && e.Result != null)
        //    {
        //        using (var ps = e.UserState as ProgressableState)
        //        {
        //            var msg = ps.State as LogMessage;
        //            if (msg != null)
        //            {
        //                var adapter = new LogMessageAdapter(msg);
        //                FacebookApi.Publish(adapter.FacebookTemplateId, adapter.FacebookTemplateData);
        //                msg.IsPublished = true;
        //            }
        //        }
        //    }
        //}
        //#endregion

        #endregion

        #region User functionality

        public User User
        {
            get { return _user; }
        }

        private void OnUserChanged(object sender, PropertyChangedEventArgs e)
        {
            GetUser();
        }

        public void InitializePreferences()
        {
            IDictionary<string, string> def = DefaultPreferences;
            foreach (string key in def.Keys)
            {
                _user.Preferences[key] = def[key];
            }
        }

        public void UpdatePreferences()
        {
            _client.UpdatePreferencesAsync(_user);
        }

        private void OnPlayingPlaylistsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            _user.Preferences["Playing"] = _playingPlaylists.Join(item => item.Id.ToString());
            UpdatePreferences();
        }

        private void InitializeUser()
        {
            _user = DefaultUser;
            Context.Post(delegate { GetUser(); }, null);
        }

        #endregion
    }
}